package com.mach.platform.api.service;

import com.mach.platform.api.domain.Attention;
import com.mach.platform.api.repository.AttentRepo;
import com.mach.platform.api.repository.MessageRepo;
import com.mach.platform.api.util.ImageUtil;
import com.mach.platform.repository.IotDevRepo;
import com.mach.platform.repository.IotSpaceRepo;
import com.mach.platform.util.SqlHelper;
import com.mach.platform.utils.springdata.Collections3;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import javax.sql.DataSource;
import javax.transaction.Transactional;
import java.math.BigInteger;
import java.sql.SQLException;
import java.time.LocalDateTime;
import java.util.*;

@Service
public class AttentServiceImpl {

    private SqlHelper sqlHelper = null;

    @Qualifier("dataSource")
    @Autowired
    private DataSource dataSource;

    @Autowired
    private AttentRepo attentRepo;

    @Autowired
    private IotSpaceRepo iotSpaceRepo;

    @Autowired
    private IotDevRepo iotDevRepo;

    @Autowired
    private MessageRepo messageRepo;


    /**
     * 获取数据库连接
     * @return
     */
    public SqlHelper getSqlHelper() {
        if (null == sqlHelper) {
            SqlHelper newSqlHelper = SqlHelper.getBySource(dataSource);
            this.sqlHelper = newSqlHelper;
            return newSqlHelper;
        }
        return sqlHelper;
    }


    /**
     * 我关注的设备组分类列表
     * @param openId
     * @return
     */
    public List attentDevSortList(String openId) {
        List<Map> attentList = attentRepo.findSortNamesByOpenId(openId);
        return Collections3.extractToList(attentList, "dev_sortName");
    }


    /**
     * 对集合按照某个字段进行降序排序
     * @param list 排序集合
     * @param orderStatus 排序字段
     */
    public void sortList(List list, String orderStatus) {
        Collections.sort(list, (Comparator<Map<String, Object>>) (o1, o2) -> {
            Integer order1 = (Integer) o1.get(orderStatus);
            Integer order2 = (Integer) o2.get(orderStatus);
            return order2.compareTo(order1);
        });
    }


    /**
     * 关注机组或者设备
     * @param openId 用户openId
     * @param id 机组菜单id或者设备id
     * @param type 关注类型 1.设备组 2.设备
     * @param stationName 所属能源站房
     * @param unitName 机组名称
     */
    public void attentDevice(String openId, Long id, int type, String stationName, String unitName, String devName) {
        Attention attention = new Attention();
        attention.setAttentLevel(2);
        attention.setAttentTime(LocalDateTime.now());
        attention.setAttentType(type);
        if (type == 1) {
            attention.setAttentName(unitName);
            attention.setDevGroupId(id);
        } else {
            attention.setDevId(id);
            attention.setDevSortName(unitName);
            attention.setAttentName(devName);
        }
        attention.setOpenId(openId);
        attention.setStationName(stationName);
        attentRepo.saveAndFlush(attention);
    }


    /**
     * 取消关注机组或者设备
     * @param openId 用户openId
     * @param type 取消关注类型 1.机组 2.设备
     * @param id 机组菜单id或者设备id
     */
    @Transactional(rollbackOn = Exception.class)
    public int cancelAttentDevice(String openId, int type, Long id) {
        int count;
        if (type == 1) {
            count = attentRepo.deleteByOpenIdTypeGroupId(openId, type, id);
        } else {
            count = attentRepo.deleteByOpenIdTypeDevId(openId, type, id);
        }
        return count;
    }


    /**
     * 设备组关注列表
     * @param openId 用户openId
     * @param orderStatus 排序字段
     * @return
     */
    public Map attentDevGroupList(String openId, String orderStatus) throws SQLException {
        SqlHelper sqlHelper = getSqlHelper();
        List<Map> attentList = attentRepo.findByTypeOpenId(openId);
        if (attentList.isEmpty()) {
            return getEmptyAttentList();
        }
        List groupIds = Collections3.extractToList(attentList, "dev_groupId");
        List<Map<String, Object>> attentNumResult = attentRepo.getAttNumByGroupIds(groupIds);
        Map groupAttent = Collections3.extractToMap(attentNumResult, "dev_groupId", "num"); // 设备组id和关注人数的对应关系
        List<Map<String, Object>> unitSpaces = iotSpaceRepo.findByParentIds(groupIds);
        List unitSpaceIds = Collections3.extractToList(unitSpaces, "unitId");
        Map groupUnit = Collections3.extractToMap(unitSpaces, "groupId", "unitId"); // 设备组id和机组空间id的对应关系
        // 查询所有机组设备空间下的所有设备
        List<Map<String, Object>> iotDevList = iotDevRepo.findBySpaceIds(unitSpaceIds);
        String devIds = Collections3.extractToString(iotDevList, "id", ",");
        // 查询设备的实时数据
        String curSql = "select dev_id, dvalue value from iot_dev_cur_data_win where dev_id in (" + devIds + ")" +
                " and data_type = '运行状态' and uptime > date_sub(now(), interval 120 second)";
        List<Map<String, Object>> curResult = sqlHelper.queryList(curSql);

        // 开始组装前端数据
        List<Map> resultList = new ArrayList();
        int devSize = iotDevList.size();
        for (int i = 0; i < attentList.size(); i++) {
            Map attent = attentList.get(i);
            int faultNum = 0; // 故障数量
            int runNum = 0; // 运行数量
            int offlineNum = 0; // 离线数量
            int standbyNum = 0; // 待机数量
            for (int j = 0; j < devSize; j++) {
                Map devMap = iotDevList.get(j);
                String groupId = attent.get("dev_groupId").toString();
                int unitId = (int) groupUnit.get(Integer.parseInt(groupId));
                int spaceId = (int) devMap.get("space_id");
                if (unitId == spaceId) {
                    for (int k = 0; k < curResult.size(); k++) {
                        Map curMap = curResult.get(k);
                        if (devMap.get("id").toString().equals(curMap.get("dev_id").toString())) {
                            double value = (double) curMap.get("value");
                            int runStatus = (int) Math.round(value);
                            if (runStatus == 0) standbyNum++;
                            else if (runStatus == 1) runNum++;
                            else if (runStatus == 2) faultNum++;
                            else if (runStatus == 3) offlineNum++;
                            break;
                        }
                    }
                    break;
                }
            }
            Map map = new HashMap();
            map.put("attentLevel", attent.get("attent_level")); // 关注程度
            String devGroupName = (String) attent.get("attent_name");
            String imagePath = ImageUtil.getImagePath(devGroupName); // 图片路径
            map.put("imagePath", imagePath);
            map.put("attentNum", groupAttent.get(attent.get("dev_groupId"))); // 关注人数
            map.put("id", attent.get("id")); // 关注id
            map.put("groupName", devGroupName); // 设备组名称
            map.put("stationName", attent.get("station_name")); // 站房名称
            map.put("faultNum", faultNum);
            map.put("runNum", runNum);
            map.put("offlineNum", offlineNum);
            map.put("standbyNum", standbyNum);
            resultList.add(map);
        }
        Map groupList = getGroupList(resultList);
        List<Map> toppingList = (List<Map>) groupList.get("topping");
        List<Map> generalList = (List<Map>) groupList.get("general");
        // 对最终结果数据进行排序
        sortList(toppingList, orderStatus);
        sortList(generalList, orderStatus);

        Map<String, Object> result = new HashMap<>();
        result.put("topping", toppingList);
        result.put("general", generalList);
        return result;
    }


    /**
     * 提取集合当中置顶关注数据和普通关注数据
     * @param resultList
     * @return
     */
    public Map getGroupList(List<Map> resultList) {
        List<Map> toppingList = new ArrayList<>(); // 置顶关注集合
        List<Map> generalList = new ArrayList<>(); // 普通关注集合
        for (Map map : resultList) {
            if ((int) map.get("attentLevel") == 1) {
                toppingList.add(map);
            } else if ((int) map.get("attentLevel") == 2) {
                generalList.add(map);
            }
        }
        Map<String, Object> result = new HashMap<>();
        result.put("topping", toppingList);
        result.put("general", generalList);
        return result;
    }


    /**
     * 取消关注设备组或者设备
     * @param ids 关注id的数组
     */
    @Transactional(rollbackOn = Exception.class)
    public boolean cancelAttent(Long[] ids) {
        try {
            attentRepo.deleteByIdIn(ids);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }


    /**
     * 取消置顶设备组/设备
     * @param id 关注id
     * @return
     */
    @Transactional(rollbackOn = Exception.class)
    public int cancelTopping(Long id) {
        return attentRepo.updateLevelById(2, id);
    }


    /**
     * 置顶设备组/设备
     * @param id 关注id
     * @return
     */
    @Transactional(rollbackOn = Exception.class)
    public int topping(Long id) {
        return attentRepo.updateLevelById(1, id);
    }


    /**
     * 统计设备的报警次数，运维次数，点检次数
     * @param messageResult
     * @param attentDevId
     */
    public Map devStatusNum(List<Map> messageResult, String attentDevId) {
        int alarmNum = 0; // 报警次数
        int maintainNum = 0; // 运维次数
        int checkNum = 0; // 点检次数
        for (Map messMap : messageResult) {
            String messDevId = messMap.get("dev_id").toString();
            if (attentDevId.equals(messDevId)) {
                int num = ((BigInteger) messMap.get("num")).intValue();
                if ((int) messMap.get("hurdles") == 1) {
                    alarmNum = num;
                }
                if ((int) messMap.get("hurdles") == 2) {
                    maintainNum = num;
                }
                if ((int) messMap.get("hurdles") == 3) {
                    checkNum = num;
                }
            }
        }
        Map result = new HashMap();
        result.put("alarmNum", alarmNum);
        result.put("maintainNum", maintainNum);
        result.put("checkNum", checkNum);
        return result;
    }


    /**
     * 找出设备的运行状态
     * @param devStatusResult
     * @param attentDevId
     */
    public int devRunStatus(List<Map<String, Object>> devStatusResult, String attentDevId) {
        int runStatus = 3; // 设备的运行状态默认是离线，实时表没有数据
        for (Map map : devStatusResult) {
            String devId = map.get("dev_id").toString();
            if (attentDevId.equals(devId)) {
                runStatus = new Double((Double) map.get("value")).intValue();
                break;
            }
        }
        return runStatus;
    }


    /**
     * 得到一个空的关注Map
     * @return
     */
    public Map getEmptyAttentList() {
        Map<String, Object> result = new HashMap<>();
        result.put("topping", new ArrayList<>());
        result.put("general", new ArrayList<>());
        return result;
    }


    /**
     * 设备关注列表
     * @param openId 用户openId
     * @param sortName 分类名称
     * @return
     */
    public Map<String, Object> attentDeviceList(String openId, String sortName) {
        SqlHelper sqlHelper = getSqlHelper();
        List<Map> attentList;
        if (sortName == null) {
            attentList = attentRepo.findDevByOpenId(openId);
        } else {
            attentList = attentRepo.findDevByOpenIdSortName(openId, sortName);
        }
        if (attentList.isEmpty()) {
            return getEmptyAttentList();
        }
        List devIds = Collections3.extractToList(attentList, "dev_id");
        // 查询每个设备的关注人数
        List<Map> devAttentNum = attentRepo.getAttNumByDevIds(devIds);
        Map devAttent = Collections3.extractToMap(devAttentNum, "dev_id", "num");
        // 查询设备的报警，运维，点检数据
        List<Map> messageResult = messageRepo.getMaintainDataByDevIds(devIds);
        // 查询全部关注设备的运行状态
        String devIdsStr = Collections3.extractToString(attentList, "dev_id", ",");
        String curSql = "select dev_id, dvalue value from iot_dev_cur_data_win where dev_id in (" + devIdsStr + ")" +
                " and data_type = '运行状态' and uptime > date_sub(now(), interval 120 second)";
        List<Map<String, Object>> devStatusResult = null;
        try {
            devStatusResult = sqlHelper.queryList(curSql);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        List<Map> resultList = new ArrayList<>();
        for (Map attentMap : attentList) {
            String attentDevId = attentMap.get("dev_id").toString();
            Map devStatusMap = devStatusNum(messageResult, attentDevId); // 统计数量
            int runStatus = devRunStatus(devStatusResult, attentDevId); // 运行状态

            Map resultMap = new HashMap();
            resultMap.put("attentLevel", attentMap.get("attent_level")); // 关注程度
            String devName = (String) attentMap.get("attent_name");
            Map imagePathMap = ImageUtil.getImagePath(devName, runStatus); // 设备图片
            resultMap.put("imagePath", imagePathMap.get("devImagePath"));
            resultMap.put("attentNum", devAttent.get(attentMap.get("dev_id"))); // 关注人数
            resultMap.put("id", attentMap.get("id")); // 关注id
            resultMap.put("devName", devName); // 设备名称
            resultMap.put("stationName", attentMap.get("station_name")); // 站房名称
            resultMap.put("alarmNum", devStatusMap.get("alarmNum")); // 报警次数
            resultMap.put("maintainNum", devStatusMap.get("maintainNum")); // 运维次数
            resultMap.put("checkNum", devStatusMap.get("checkNum")); // 点检次数
            resultList.add(resultMap);
        }
        Map groupList = getGroupList(resultList);
        List<Map> toppingList = (List<Map>) groupList.get("topping");
        List<Map> generalList = (List<Map>) groupList.get("general");

        Map<String, Object> result = new HashMap<>();
        result.put("topping", toppingList);
        result.put("general", generalList);
        return result;
    }


}
